home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
System Booster
/
System Booster.iso
/
Texteditors
/
XDME
/
Src
/
Var
/
VarsBases.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-09-26
|
12KB
|
588 lines
#define PATCH_AVL
/******************************************************************************
MODUL
varsbases.c
DESCRIPTION
lowlevel Variable support for DME/XDME
(Basic List/AVL-Tree Functions)
NOTES
Either use AVLTREES or MLISTS
For ALL commands (even to the searches) You must use
the address of a tree/list, not the tree/list itself
(that was done to simplify source-modification: just
replace 'List'/[M]LIST by 'Tree'/APTR, and go)
BUGS
<none known>
TODO
More homogene Interface - Use of an opaque type
(So that silly redefinition in other modules can go away)
EXAMPLES
-/-
SEE ALSO
vars.c
INDEX
HISTORY
<see RCS-File>
******************************************************************************/
/*
** (C)Copyright 1992 by Bernd Noll for null/zero-soft
** All Rights Reserved
**
** RCS Header: $Id: varsbases.c,v 1.65 92/12/04 21:00:32 b_noll Exp $
**
** Basic Functions to work with trees/lists of DME-Variables
** Put together to start a little bit of modularisation
** in the sources.
**
*/
/**************************************
Includes
**************************************/
#define TNODE struct TreeNode
#define VARS struct _VARS
#define VBASE TNODE *
#include "defs.h"
#include "AVL.h"
/**************************************
Exports
**************************************/
/* --- You can only use either LISTS or AVL-Trees!!! */
/* Vars Operations on trees */
Prototype void DelAllVarsFromTree ( VBASE * tree );
Prototype void DelVarFromTree ( VBASE * tree, char * name );
Prototype char * GetVarFromTree ( VBASE * tree, char * name );
Prototype void SetVarIntoTree ( VBASE * tree, char * name, char * value );
/* Lists Operations in Common */
Prototype char* names2string ( MLIST* list, char* buffer, char delimiter, void* filter ); /* assumes buffer is 1/4k * BUFFERS chgars long */
Prototype int numnodes ( MLIST* list );
Prototype NODE* findnode ( MLIST* list, char* name, short len );
/* Vars Operations on lists */
Prototype void DelAllVarsFromList ( MLIST* list );
Prototype void DelVarFromList ( MLIST* list, char* name );
Prototype char* GetVarFromList ( MLIST* list, char* name );
Prototype void SetVarIntoList ( MLIST* list, char* name, char* value );
/**************************************
Interne Defines & Strukturen
**************************************/
#ifdef PATCH_AVL
# ifdef TEST
# define error printf
# define nomemory()
# endif
struct _VARS
{
TNODE Node;
char * Str;
};
#else
typedef struct _VARS
{
NODE Node;
char * Str;
};
#define VBASE MLIST
#endif /* (not) PATCH_AVL */
/**************************************
Implementation
**************************************/
#ifdef PATCH_AVL
/*
** DelAllVarsFromTree()
** recursively remove all nodes from a certain tree
** and free them and their associated names&values
*/
void
DelAllVarsFromTree (VBASE * tree)
{
if (!tree || !(*tree)) {
return;
} /* if */
DelAllVarsFromTree(&(*tree)->tn_Left); /* first free its sons */
DelAllVarsFromTree(&(*tree)->tn_Right);
free((*tree)->tn_Name); /* then free it and all its subs */
free(((VARS*)*tree)->Str);
free((*tree));
} /* DelAllVarsFromTree */
/*
** SetVarIntoTree()
** define a node with a cetain name and value in
** a given tree if therew is already a node of the
** chosen name the previous node is removed
** (actually only the old value is removed)
** if any allocation went wrong, call nomemory()
*/
void
SetVarIntoTree (VBASE* tree, char* name, char* value)
{
VARS* v = NULL;
char* vn = NULL;
char* vv = NULL;
if ((v = (VARS*)AVL_Find(tree, name)))
{
if ((vv = strdup(value)))
{
free(v->Str);
v->Str = vv;
return;
} /* if malloced */
v = NULL; /* avoid freeing the found node */
} else
{
v = malloc(sizeof(VARS));
vv = strdup(value);
vn = strdup(name);
if (v && vv && vn)
{
v->Str = vv;
v->Node.tn_Name = vn;
AVL_Append (tree, (TNODE *)v);
return;
} /* if malloced */
} /* if (no) old node */
/* --- if we didn't return prior, (if everything worked fine) remove all allocated data */
if (v) free(v);
if (vv) free(vv);
if (vn) free(vn);
nomemory();
abort2();
} /* SetVarIntoTree */
/*
** DelVarFromTree()
** remove a certain node (found w/ FindTreeNode)
** from a given tree; do not panik, if there is no
** node found
*/
void
DelVarFromTree (VBASE* tree, char* name)
{
VARS *v = NULL;
if ((v = (VARS*)AVL_Find(tree, name)))
{ /* if there is a node of the right name */
AVL_Remove (tree, (TNODE *)v); /* remove it and all its subs */
free(v->Node.tn_Name);
free(v->Str);
free(v);
} /* if */
} /* DelVarFromTree */
/*
** GetVarFromTree()
** find a node in a certain tree (w/ FindTreeNode)
** duplicate its value and return the copy
** return NULL if there was no node found
** and call nomemory() if duplicate failed
*/
char*
GetVarFromTree (VBASE* tree, char* name)
{
char* str = NULL;
VARS* v = NULL;
if ((v = (VARS*)AVL_Find(tree, name)))
{ /* if there is a node of the right name */
if ((str = strdup(v->Str)))
{ /* return a copy of its value */
return(str);
} else
{
nomemory();
abort(NULL);
} /* if */
} /* if */
return(NULL);
} /* GetVarFromTree */
#ifdef TEST
void zeigebaum(TNODE* t)
{
if (t==NULL)
{
printf( "-" );
return;
}
printf("(%d%s ",t->tn_Balance,t->tn_Name);
printf("L");
zeigebaum(t->tn_Left);
printf("R");
zeigebaum(t->tn_Right);
printf(")");
} /* zeigebaum */
char* testnamen[] =
{
"prag",
"lima",
"tokio",
"bonn",
"paris",
"sofia",
"wien",
"bern",
"kairo",
"oslo",
"rom",
"athen",
NULL };
int main(int ac, char* av[])
{
char** tt;
char buffer [100];
TNODE* staedte = NULL;
TNODE* rem = NULL;
for (tt = testnamen; *tt; tt++)
{
printf(">%s\n",*tt);
SetVarIntoTree(&staedte, *tt, "");
/* gets (buffer); */
} /* for */
zeigebaum (staedte);
rem = AVL_Find (&staedte, "bonn");
printf ("\nrem == %08lx %s\n", rem, rem->tn_Name);
AVL_Remove (&staedte, rem);
zeigebaum(staedte);
puts ("");
} /* main */
#endif /* TEST */
#else /* ! PATCH_AVL */
/*
** GetVarFromList()
** find a node in a certain list (w/ FindName)
** duplicate its value and return the copy
** return NULL if there was no node found
** and call nomemory() if duplicate failed
*/
char*
GetVarFromList (VBASE* list, char* name)
{
char* str = NULL;
VARS* v = NULL;
if ((v = (VARS*)FindName((LIST*)list, name)))
{ /* if there is a node of the right name */
if ((str = strdup(v->Str)))
{ /* return a copy of its value */
return(str);
} else
{
nomemory();
abort(NULL);
} /* if */
} /* if */
return(NULL);
} /* GetVarFromList */
/*
** DelVarFromList()
** remove a certain node (found w/ FindName)
** from a given list; do not panik, if there is no
** node found
*/
void
DelVarFromList (VBASE* list, char* name)
{
VARS *v = NULL;
if ((v = (VARS*)FindName((LIST*)list, name)))
{ /* if there is a node of the right name */
Remove((NODE *)v); /* remove it and all its subs */
free(v->Node.ln_Name);
free(v->Str);
free(v);
} /* if */
} /* DelVarFromList */
/*
** DelAllVarsFromList()
** remove all nodes from a certain list
** and free them and their associated names&values
*/
void
DelAllVarsFromList (VBASE* list)
{
VARS* v = NULL;
while ((v = (VARS*)RemHead((LIST*)list)))
{ /* while there is an entry left in the list */
free(v->Node.ln_Name); /* free it and all its subs */
free(v->Str);
free(v);
} /* while */
} /* DelAllVarsFromList */
/*
** SetVarIntoList()
** define a node with a cetain name and value in
** a given list if therew is already a node of the
** chosen name the previous node is removed
** (actually only the old value is removed)
** if any allocation went wrong, call nomemory()
*/
void
SetVarIntoList (VBASE* list, char* name, char* value)
{
VARS* v = NULL;
char* vn = NULL;
char* vv = NULL;
#ifdef N_DEF
/* --- First it is checked, if You have a Special variable */
/*
** these checks may be object of some changes in near future
** - I do now think, that it would be quite better
** to introduce a new function SETSPC for special variables
** and to call "SETLOCAL <num>" to set a local flag instead of "SET i<num>"
*/
if (SetAnyFlag(name, value) || SetSpecialInt(name, value)
|| SetSpecialVar(name, value) )
{
return();
} /* if */
#endif /* N_DEF */
/*
** that routine is a little bit longer than the old one,
** but we need not free all data of older entries any
** more, so memory fragmentation should be reduced a bit:
** if there's an older entry, simply replace its value
** by the new one, else create a full new entry.
*/
if ((v = (VARS*)FindName((LIST*)list, name)))
{
if (vv = strdup(value))
{
free(v->Str);
v->Str = vv;
/* --- it might be senseful moving the changed entry to startoflist */
/* Remove(v); */
/* AddHead((LIST*)list, v) */
return;
} /* if malloced */
v = NULL; /* avoid removing the found node */
} else
{
v = malloc(sizeof(VARS));
vv = strdup(value);
vn = strdup(name);
if (v && vv && vn)
{
v->Str = vv;
v->Node.ln_Name = vn;
AddHead((LIST *)list, (NODE *)v);
return;
} /* if malloced */
} /* if (no) old node */
/* --- if we didn't return prior, (if everything worked fine) remove all allocated data */
if (v) free(v);
if (vv) free(vv);
if (vn) free(vn);
nomemory();
abort2();
} /* SetVarIntoList */
/*
** Names 2 String
** copies all ln_Name s of a given List into a String and returns it
** (if filter != NULL the names are filtered before)
** There _must_ be a buffer big enough to fit all the Strings:
** definements in defs.h:
** BUFFERS is the number of "LINES" reserved for buffer
** and LINE_LENGTH (== 256) is the length of one such line
** <exec/lists.h> should be included
**
** name2string does _not_ allocate memory!!!!
** currently filter MUST BE SET to NULL to guarantee compatibility to later versions!
** list MUST BE VALID! (there is no check)
*/
char*
names2string (MLIST* list, char* buffer, char delimiter, char* (*filter)())
{
struct Node* node;
char* buf = buffer;
int i = 0;
char delim[2] =
{delimiter,0};
/* char inter[128]; */
node = (NODE*)list->mlh_Head;
while (node->ln_Succ && node != (NODE*)&list->mlh_Tail)
{
buffer = buf+i;
/* ************************************ Hier gehoert noch der filter hin, ich brauchte ihn nur bisher noch nicht, daher liess ich ihn weg * */
if ((i += strlen(node->ln_Name)) < BUFFERS*LINE_LENGTH-1)
{
strcpy(buffer, node->ln_Name);
if (i < BUFFERS*LINE_LENGTH-1)
{
buffer = buf+i;
strcpy(buffer, delim);
i++;
} else
{
return(buf);
} /* if */
} else
{
break;
} /* if */
node = node->ln_Succ;
} /* while */
*buffer = 0;
return(buf);
} /* names2string */
/*
** numnodes() - return the number of entries in a list
**
** list MUST BE VALID! (there is no check)
*/
int
numnodes(MLIST* list)
{
register int i = 0;
register MNODE* n;
for (n = list->mlh_Head; (n != NULL) && (n->mln_Succ != NULL); n = n->mln_Succ)
{
i++;
} /* for */
return(i);
} /* numnodes */
/*
** findnode() - find a certain node in a list
**
** search may be done up to a certain strlength (own function) or via FindName
**
** list MUST BE VALID! (there is no check)
*/
NODE*
findnode(MLIST* list, char* name, short len)
{
register NODE* node;
if (len)
{
for (node = (NODE*)list->mlh_Head; node && node->ln_Succ; node = node->ln_Succ)
{
if (strncmp(node->ln_Name, name, len) == 0)
{
return(node);
} /* if */
} /* for */
} else
{
return(FindName((LIST*)list, name));
} /* if */
return(NULL);
} /* findnode */
#endif /* (not) PATCH_AVL */
/******************************************************************************
***** ENDE varsbases.c
******************************************************************************/